package com.cqupt.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.cqupt.service.DashBoardService;
import com.cqupt.utils.APIUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author
 * @version
 * @description:
 * @date
 */

@Service
@Transactional
public class DashBoardServiceImpl implements DashBoardService {
    /**
     * @description: 获取各种状态下的主机数目
     * @param:
     * @return:
     * @author
     * @date:
     */
    @Override
    public Map<String, Object> getNumbersOfHostInDifferentType() {
        final String token = APIUtils.getToken();
        final String[] outputs = {"available","snmp_available", "ipmi_available", "jmx_available"};

        Map<String, Object> paramsMap = new HashMap<String, Object>(){{
            put("jsonrpc", "2.0");
            put("method", "host.get");
            put("id", 1);
            put("auth", token);
            put("params", new HashMap<String, Object>(){{
                put("output", outputs);
            }});
        }};

        Map<String, Object> hostMap = APIUtils.sendRequest(JSON.toJSONString(paramsMap, SerializerFeature.WriteMapNullValue));
        List<Map<String, Object>> hostList = (List<Map<String, Object>>) hostMap.get("result");
//      可用主机数量
        int aviNumber = 0;
//      其它未知主机数量
        int unknownNumber = 0;
//      不可用主机数量
        int unaviNumber = 0;
//      所有主机总数
        int total = 0;

        for (Map<String, Object> host: hostList){
            int numZabbix = Integer.parseInt(host.get("available").toString());
            int numSnmp = Integer.parseInt(host.get("snmp_available").toString());
            int numIpmi = Integer.parseInt(host.get("ipmi_available").toString());
            int numJmx = Integer.parseInt(host.get("jmx_available").toString());

            if (numZabbix == 1 || numIpmi == 1 || numJmx == 1 || numSnmp == 1){ // 可用
                aviNumber++;
            } else if (numZabbix == 2 || numIpmi == 2 || numJmx == 2 || numSnmp == 2){  // 不可用
                unaviNumber++;
            }else { //其它状态
                unknownNumber++;
            }
            total++;
        }
//      最终得到各状态下主机数量
        Integer finalAviNumber = aviNumber;
        Integer finalUnaviNumber = unaviNumber;
        Integer finalUnknownNumber = unknownNumber;
        Integer finalTotal = total;

        return new HashMap<String, Object>(){{
            put("available", finalAviNumber);
            put("unaviNumber", finalUnaviNumber);
            put("unknownNumber", finalUnknownNumber);
            put("total", finalTotal);
        }};
    }

    /**
     * 获取不同类型告警数量
     * @return
     */
    @Override
    public List<Map<String, Object>> getNumberOfProblemDifferentType() {
        final String token = APIUtils.getToken();
        Map<String, Object> paramsMap = new HashMap<String, Object>(){{
            put("jsonrpc", "2.0");
            put("method", "problem.get");
            put("id", 1);
            put("auth", token);
            put("params", new HashMap<String, Object>(){{
                put("output","extend");
                put("selectAcknowledges","extend");
                put("selectTags","extend");
                put("recent","true");
            }});
        }};
        Map<String, Object> responseMap = APIUtils.sendRequest(JSON.toJSONString(paramsMap, SerializerFeature.WriteMapNullValue));
        List<Map<String, Object>> resultList = (List<Map<String, Object>>)responseMap.get("result");
        return resultList;
    }

    /**
     *
     * @description: 获取主机列表
     * @param:
     * @return:
     * @author:
     * @time:
     */
    public List<Map<String, Object>> getAllOnlineHost() {
        final String token = APIUtils.getToken();
        Map<String, Object> paramsMap = new HashMap<String, Object>(){{
            put("jsonrpc", "2.0");
            put("method", "host.get");
            put("id", 1);
            put("auth", token);
            put("params", new HashMap<String, Object>(){{
                put("filter", new HashMap<String, Object>(){{
                    put("monitored_hosts", true);
                }});
            }});
        }};
        Map<String, Object> responseMap = APIUtils.sendRequest(JSON.toJSONString(paramsMap, SerializerFeature.WriteMapNullValue));
        List<Map<String, Object>> resultList = (List<Map<String, Object>>)responseMap.get("result");
        return resultList;
    }

    /**
     *
     * @description: 根据cpu 内存利用率统计主机数量
     * @param:
     * @return:
     * @author:
     * @time:
     */
    public Map<String, Object> getInfoClassifiedByCpuAndMemoryUtilization() {
//      获取主机列表
        List<Map<String, Object>> allOnlineHost = getAllOnlineHost();
        List<String> ids = new ArrayList<>();
        for (Map<String, Object> map : allOnlineHost) {
            ids.add(map.get("hostid").toString());
        }
        Map<String, Object> result = new HashMap<>();
//      获取CPU利用率监控项
        List<Map<String, Object>> cpuMapList = getItemInfoByIdsAndItemName(ids, "CPU utilization");
//      获取内存利用率监控项
        List<Map<String, Object>> memoryMapList = getItemInfoByIdsAndItemName(ids, "memory utilization");
        System.out.println(cpuMapList);
        System.out.println(memoryMapList);
        result = getCpuAndMemoryMap(cpuMapList,memoryMapList);
        return result;
    }

    /**
     * @description 将List<MAP<K,V>>归类
     * @param cpuMapList
     * @param memoryMapList
     * @return
     */
    public Map<String,Object> getCpuAndMemoryMap(List<Map<String, Object>> cpuMapList,List<Map<String, Object>> memoryMapList){
        Map<String, Object> result = new HashMap<>();
//      将cpu利用率和内存利用率分段计数
//      0-10%,10%-20%,...,以此类推进行分段
        int cpu_0_10 = 0, cpu_10_20 = 0, cpu_20_30 = 0, cpu_30_40 = 0, cpu_40_50 = 0, cpu_50_60 = 0, cpu_60_70 = 0, cpu_70_80 = 0, cpu_80_90 = 0, cpu_90_100 = 0;
        int memory_0_10 = 0, memory_10_20 = 0, memory_20_30 = 0, memory_30_40 = 0, memory_40_50 = 0, memory_50_60 = 0, memory_60_70 = 0, memory_70_80 = 0, memory_80_90 = 0, memory_90_100 = 0;
//      计算cpu各区间利用率的主机数量
        for (Map<String, Object> cpuMap : cpuMapList) {
            Double cpuUtilization = Double.valueOf(cpuMap.get("lastvalue").toString());
            int level = cpuUtilization.intValue()/10;
            switch (level){
                case 0: {cpu_0_10++;break;}
                case 1: {cpu_10_20++;break;}
                case 2: {cpu_20_30++;break;}
                case 3: {cpu_30_40++;break;}
                case 4: {cpu_40_50++;break;}
                case 5: {cpu_50_60++;break;}
                case 6: {cpu_60_70++;break;}
                case 7: {cpu_70_80++;break;}
                case 8: {cpu_80_90++;break;}
                default:cpu_90_100++;
            }
        }
//      计算内存各区间利用率的主机数量
        for (Map<String, Object> memoryMap : memoryMapList) {
            Double memoryUtilization = Double.valueOf(memoryMap.get("lastvalue").toString());
            int level = memoryUtilization.intValue()/10;
            switch (level){
                case 0: {memory_0_10++;break;}
                case 1: {memory_10_20++;break;}
                case 2: {memory_20_30++;break;}
                case 3: {memory_30_40++;break;}
                case 4: {memory_40_50++;break;}
                case 5: {memory_50_60++;break;}
                case 6: {memory_60_70++;break;}
                case 7: {memory_70_80++;break;}
                case 8: {memory_80_90++;break;}
                default:memory_90_100++;
            }
    }
//      按 cpu 和内存利用率分别封装
        List<Integer> cpuClassfy = new ArrayList<>();
        List<Integer> memeoryClassfy = new ArrayList<>();
        cpuClassfy.add(cpu_0_10);
        cpuClassfy.add(cpu_10_20);
        cpuClassfy.add(cpu_20_30);
        cpuClassfy.add(cpu_30_40);
        cpuClassfy.add(cpu_40_50);
        cpuClassfy.add(cpu_50_60);
        cpuClassfy.add(cpu_60_70);
        cpuClassfy.add(cpu_70_80);
        cpuClassfy.add(cpu_80_90);
        cpuClassfy.add(cpu_90_100);
        memeoryClassfy.add(memory_0_10);
        memeoryClassfy.add(memory_10_20);
        memeoryClassfy.add(memory_20_30);
        memeoryClassfy.add(memory_30_40);
        memeoryClassfy.add(memory_40_50);
        memeoryClassfy.add(memory_50_60);
        memeoryClassfy.add(memory_60_70);
        memeoryClassfy.add(memory_70_80);
        memeoryClassfy.add(memory_80_90);
        memeoryClassfy.add(memory_90_100);
        result.put("CPU",cpuClassfy);
        result.put("Memory",memeoryClassfy);
        return result;
    }
    /**
     *
     * @description:  根据主机id和监控项名称查询监控项
     * @param:
     * @return:
     * @author:
     * @time:
     */
    public List<Map<String, Object>> getItemInfoByIdsAndItemName(List<String> ids, String name){
        final String token = APIUtils.getToken();
        Map<String, Object> itemMap = new HashMap<String, Object>(){{
            put("jsonrpc", "2.0");
            put("method", "item.get");
            put("id", 1);
            put("auth", token);
            put("params", new HashMap<String, Object>(){{
                put("output", "extend");
                put("hostids", ids);
                put("search", new HashMap<String, Object>(){{
                    put("name", name);
                }});
            }});
        }};
        Map<String, Object> responseMap = APIUtils.sendRequest(JSON.toJSONString(itemMap, SerializerFeature.WriteMapNullValue));
        return (List<Map<String, Object>>) responseMap.get("result");
    }

    /**
     * @description 获取高负载设备
     * @param name
     * @return
     */
    public List<Map<String, Object>> getHighLoadList(String name) {
        MonitorServiceImpl monitorService = new MonitorServiceImpl();
        List<Map<String, Object>> highLoadHostList = monitorService.getHighLoadHostList_new(name);
        int size = highLoadHostList.size();
        if(size>5){
            highLoadHostList = highLoadHostList.subList(0, 5);
        }else{
            highLoadHostList = highLoadHostList.subList(0, size);
        }
        return highLoadHostList;
    }
}
